import { useDraggable } from '@vueuse/core'
import { computed, CSSProperties, ref, watch, watchEffect } from 'vue'

export default function draggable(target: HTMLElement) {
	const { x, y, isDragging } = useDraggable(target),
		startX = ref<number>(0),
		startY = ref<number>(0),
		startedDrag = ref<boolean>(false),
		transformX = ref<number>(0),
		transformY = ref<number>(0),
		preTransformX = ref<number>(0),
		preTransformY = ref<number>(0),
		dragRect = ref({ left: 0, right: 0, top: 0, bottom: 0 })
	watch([x, y], () => {
		if (!startedDrag.value) {
			startX.value = x.value
			startY.value = y.value
			const bodyRect = document.body.getBoundingClientRect()
			// @ts-ignore
			const titleRect = target.value.getBoundingClientRect()
			dragRect.value.right = bodyRect.width - titleRect.width
			dragRect.value.bottom = bodyRect.height - titleRect.height
			preTransformX.value = transformX.value
			preTransformY.value = transformY.value
		}
		startedDrag.value = true
	})
	watch(isDragging, () => {
		if (!isDragging) {
			startedDrag.value = false
		}
	})
	watchEffect(() => {
		if (startedDrag.value) {
			transformX.value =
				preTransformX.value +
				Math.min(
					Math.max(dragRect.value.left, x.value),
					dragRect.value.right,
				) -
				startX.value
			transformY.value =
				preTransformY.value +
				Math.min(
					Math.max(dragRect.value.top, y.value),
					dragRect.value.bottom,
				) -
				startY.value
		}
	})
	return computed<CSSProperties>(() => {
		return {
			transform: `translate(${transformX.value}px, ${transformY.value}px)`,
		}
	})
}
